import React from 'react';
import ReactDOM from 'react-dom'
import './index.css';
import View from './View'
import registerServiceWorker from './registerServiceWorker'
import initialState from './model'

class App extends React.Component {
  constructor() {
    super()
    this.state = initialState
    this.events = {
      'click .js_panel_item': 'handleClickPanelItem',
    }
    // todo with arrow function
    this.handleClickPanelItem = this.handleClickPanelItem.bind(this)
    this.calculate = this.calculate.bind(this)
  }
  componentDidMount() {
    this.addEvents()
  }
  componentWillUnmount() {
    this.removeEvents()
  }
  render() {
    return (
      <View state={this.state} />
    )
  }
  addEvents() {
    const { events } = this
    Object.keys(events).forEach(key => {
      const [eventType, ...selectors] = key.split(' ')
      selectors.forEach(selector => {
        const elements = document.querySelectorAll(selector)
        const handler = this[events[key]]
        if ('function' === typeof handler) {
          Array.from(elements).forEach(element => {
            element.addEventListener(eventType, handler)
          })
        }
      })
    })
  }
  removeEvents() {
    const { events } = this
    Object.keys(events).forEach(key => {
      const [eventType, ...selectors] = key.split(' ')
      selectors.forEach(selector => {
        const elements = document.querySelectorAll(selector)
        const handler = this[events[key]]
        if ('function' === typeof handler) {
          Array.from(elements).forEach(element => {
            element.removeEventListener(eventType, handler)
          })
        }
      })
    })
  }
  calculate(num) {
    const { operator, preVal, autoCalc } = this.state
    if (preVal === null || autoCalc) {
      return num
    }
    switch (operator) {
      case '+': return preVal + num
      case '-': return preVal - num
      case 'x': return preVal * num
      case '÷': return preVal / num
    }
  }
  handleClickPanelItem({ currentTarget }) {
    const { val, panels, preVal, operator, autoCalc } = this.state
    const payload = JSON.parse(currentTarget.getAttribute('data-payload'))
    const {
      text,
      isDecimalPoint,
      reset,
    } = payload
    if ('number' === typeof text) {
      let display = Number(val + '' + text)
      this.setState({
        val: display
      })
    } else if (isDecimalPoint) {
      let display = val + '.'
      display = toFloat(display, val)
      this.setState({
        val: display
      })
    } else if (reset) {
      const newPanels = panels.map(panel => {
        if (!panel.reset) {
          return panel
        }
        return {
          ...panel,
          reset: false,
          backspace: true,
          text: 'C'
        }
      })
      this.setState({
        val: 0,
        panels: newPanels
      })
    } else if (payload.backspace) {
      const newPanels = panels.map(panel => {
        if (!panel.backspace) {
          return panel
        }
        const smallThenTen = val < 10
        return {
          ...panel,
          backspace: !smallThenTen,
          reset: smallThenTen,
          text: smallThenTen ? 'AC' : 'C'
        }
      })
      if (val) {
        this.setState({
          val: Number(String(val).slice(0, -1)),
          panels: newPanels
        })
      }
    } else if (payload.switch) {
      let newVal = Math.abs(val)
      if (val > 0) {
        newVal = -newVal
      }
      this.setState({
        val: newVal
      })
    } else if (payload.isOperator) {
      const newAutoCalc = operator !== undefined ? true : autoCalc
      const newVal = payload.operator === '=' ? preVal : val
      this.setState({
        preVal: val,
        operator: payload.text,
        autoCalc: newAutoCalc,
        val: newVal
      })
    }
  }
}

function toFloat(currentValue, oldValue) {
  const prev = currentValue
  currentValue = Number(currentValue)
  if (isNaN(currentValue)) {
    return oldValue
  }
  const idx = String(prev).indexOf('.')
  if (idx !== -1) {
    if (String(prev).slice(idx).length > 3) {
      // 不进行四舍五入
      const result = prev.match(/^-?\d+(?:\.\d{0,2})?/)
      if (!result[0]) {
        return oldValue
      }
      return result[0]
    }
    return prev
  }
  return currentValue
}

ReactDOM.render(<App />, document.getElementById('root'))
registerServiceWorker()
